package mediator;

import java.awt.Dimension;
import java.awt.Point;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.StringReader;
import java.util.LinkedList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import objectsDiagram.Condition;
import objectsDiagram.DecoratorTask;
import objectsDiagram.Diagram;
import objectsDiagram.Flow;
import objectsDiagram.Input;
import objectsDiagram.Output;
import objectsDiagram.State;
import objectsDiagram.Task;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

public class ReadXML{

	private static final int RANGE_FLOW = 10;

	private Diagram diagram;

	private LinkedList<String> noNetsList;
	private LinkedList<String> netsList;
	private LinkedList<Diagram> diagramsNetwork = new LinkedList<Diagram>();


	public ReadXML(){
		this.diagram =  new Diagram();
	}

	public void parseXMLtoDiagram(String yawlFile){
		try {
			diagram.cleanDiagram();
			File url = new File(yawlFile);

			BufferedReader br = new BufferedReader(new FileReader(url));
			String line;
			String str="";

			while ((line = br.readLine()) != null){str = str+ line;}

			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();

			InputSource file = new InputSource();
			file.setCharacterStream(new StringReader(str)); 

			Document document = db.parse(file);
			document.getDocumentElement().normalize();
			noNetsList = new LinkedList<String>();
			netsList = new LinkedList<String>();
			parseDecomposite(document, null,noNetsList,netsList,diagramsNetwork);
		}catch (Exception e) {e.printStackTrace();}
	}

	//*****************
	private void parseDecomposite(Document doc,Element elem, LinkedList<String> noNetList,LinkedList<String> netList, LinkedList<Diagram> currentNetwork){
		noNetsList = noNetList;
		netsList = netList;
		NodeList nodeDecList = doc.getElementsByTagName("decomposition");
		String idDecomp;
		for(int d=0;d<nodeDecList.getLength();d++){
			Node decNode = nodeDecList.item(d);
			Element decElement = (Element) decNode;

			NamedNodeMap elementDecList = decElement.getAttributes();
			Node idAttr = elementDecList.getNamedItem( "id" );
			idDecomp = idAttr.getNodeValue();

			Node typeAttr = elementDecList.getNamedItem( "xsi:type" );
			String typeDecomp = typeAttr.getNodeValue();

			if(typeDecomp.compareTo("NetFactsType")==0 && !netsList.contains(idDecomp)){
				ReadXML nextRead = new ReadXML();
				nextRead.getDiagram().setId(idDecomp);
				currentNetwork.addLast(nextRead.getDiagram());
				netsList.add(idDecomp);
				nextRead.parseInput(decElement);
				nextRead.parseCondition(decElement);
				nextRead.parseTask(doc,decElement,noNetsList,netsList,currentNetwork);
				nextRead.setCompositeTask(netsList);
				nextRead.parseOutput(decElement);

				NodeList nodeNetList = doc.getElementsByTagName("net");
				for(int n=0;n<nodeNetList.getLength();n++){
					Node netNode = nodeNetList.item(n);
					Element netElement = (Element) netNode;

					NamedNodeMap elementNetList = netElement.getAttributes();
					Node idNetAttr = elementNetList.getNamedItem( "id" );
					String idNet = idNetAttr.getNodeValue();

					if(idDecomp.compareTo(idNet)==0){
						nextRead.parseNet(netElement,idDecomp);
					}
				}
			}else{
				noNetsList.add(idDecomp);
			}
		}		
	}

	private void parseNet(Element elem,String idNet){	
		setSize(elem);

		NodeList nodeContainerList = elem.getElementsByTagName("container");
		for(int c = 0; c < nodeContainerList.getLength(); c++){
			Node containerNode = nodeContainerList.item(c);
			Element containerElement = (Element) containerNode;

			NamedNodeMap conteinerElementList = containerElement.getAttributes();
			Node aAttr = conteinerElementList.getNamedItem( "id" );
			String id = aAttr.getNodeValue();

			//Vertex from the container
			NodeList nodeVertexList = containerElement.getElementsByTagName("vertex");
			Node vertexNode = nodeVertexList.item(0);
			NodeList nodeAttributesList = ((Element)vertexNode).getElementsByTagName("attributes");
			Node attributesNode = nodeAttributesList.item(0);
			NodeList nodeBoundsList = ((Element)attributesNode).getElementsByTagName("bounds");
			Node boundsNode = nodeBoundsList.item(0);

			NamedNodeMap boundsNodeAttr = boundsNode.getAttributes();

			if(isTask(id)){
				getTaskById(id).setId(id);
				Node nodeValueX = boundsNodeAttr.getNamedItem( "x" );
				getTaskById(id).setCoordX((int)Float.parseFloat(parseFloat(nodeValueX.getNodeValue())));
				Node nodeValueY = boundsNodeAttr.getNamedItem( "y" );
				getTaskById(id).setCoordY((int)Float.parseFloat(parseFloat(nodeValueY.getNodeValue())));
				Node nodeValueW = boundsNodeAttr.getNamedItem( "w" );
				getTaskById(id).setWidth((int)Float.parseFloat(parseFloat(nodeValueW.getNodeValue())));
				Node nodeValueH = boundsNodeAttr.getNamedItem( "h" );
				getTaskById(id).setHeight((int)Float.parseFloat(parseFloat(nodeValueH.getNodeValue())));
			}else{
				if(isCondition(id)){
					Node nodeValueX = boundsNodeAttr.getNamedItem( "x" );
					getConditionById(id).setCoordX((int)Float.parseFloat(parseFloat(nodeValueX.getNodeValue())));
					Node nodeValueY = boundsNodeAttr.getNamedItem( "y" );
					getConditionById(id).setCoordY((int)Float.parseFloat(parseFloat(nodeValueY.getNodeValue())));
					Node nodeValueW = boundsNodeAttr.getNamedItem( "w" );
					getConditionById(id).setWidth((int)Float.parseFloat(parseFloat(nodeValueW.getNodeValue())));
					Node nodeValueH = boundsNodeAttr.getNamedItem( "h" );
					getConditionById(id).setHeight((int)Float.parseFloat(parseFloat(nodeValueH.getNodeValue())));
				}else{
					if(isOutput(id)){
						Node nodeValueX = boundsNodeAttr.getNamedItem( "x" );
						getOutput(id).setCoordX((int)Float.parseFloat(parseFloat(nodeValueX.getNodeValue())));
						Node nodeValueY = boundsNodeAttr.getNamedItem( "y" );
						getOutput(id).setCoordY((int)Float.parseFloat(parseFloat(nodeValueY.getNodeValue())));
						Node nodeValueW = boundsNodeAttr.getNamedItem( "w" );
						getOutput(id).setWidth((int)Float.parseFloat(parseFloat(nodeValueW.getNodeValue())));
						Node nodeValueH = boundsNodeAttr.getNamedItem( "h" );
						getOutput(id).setHeight((int)Float.parseFloat(parseFloat(nodeValueH.getNodeValue())));
					}

				}
			}
			//-------------------------------------------------------------------------------------------------------------------------
			//				LABELS			
			//-------------------------------------------------------------------------------------------------------------------------		
			//Label from the container
			if(isTask(id)){
				if(getTaskById(id).getName()!=null){
					NodeList nodeLabelList = containerElement.getElementsByTagName("label");
					Node labelNode = nodeLabelList.item(0);
					nodeAttributesList = ((Element)labelNode).getElementsByTagName("attributes");
					attributesNode = nodeAttributesList.item(0);
					nodeBoundsList = ((Element)attributesNode).getElementsByTagName("bounds");
					boundsNode = nodeBoundsList.item(0);

					int middlePoint = getTaskById(id).getCoordX();
					int nameRange = getTaskById(id).getName().length()/2;
					boundsNodeAttr = boundsNode.getAttributes();
					Node nodeValue = boundsNodeAttr.getNamedItem( "x" );
					getTaskById(id).setCoordLabX(middlePoint-(nameRange*6));
					nodeValue = boundsNodeAttr.getNamedItem( "y" );
					getTaskById(id).setCoordLabY((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue()))+10);
					nodeValue = boundsNodeAttr.getNamedItem( "w" );
					getTaskById(id).setWidthLab((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue())));
					nodeValue = boundsNodeAttr.getNamedItem( "h" );
					getTaskById(id).setHeightLab((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue())));
				}
			}
			if(isCondition(id)){
				if(getConditionById(id).getName()!=null){
					NodeList nodeLabelList = containerElement.getElementsByTagName("label");
					Node labelNode = nodeLabelList.item(0);
					nodeAttributesList = ((Element)labelNode).getElementsByTagName("attributes");
					attributesNode = nodeAttributesList.item(0);
					nodeBoundsList = ((Element)attributesNode).getElementsByTagName("bounds");
					boundsNode = nodeBoundsList.item(0);

					boundsNodeAttr = boundsNode.getAttributes();
					Node nodeValue = boundsNodeAttr.getNamedItem("x");
					getConditionById(id).setCoordLabX((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue()))+40);
					nodeValue = boundsNodeAttr.getNamedItem("y");
					getConditionById(id).setCoordLabY((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue()))-40);
					nodeValue = boundsNodeAttr.getNamedItem("w");
					getConditionById(id).setWidthLab((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue())));
					nodeValue = boundsNodeAttr.getNamedItem("h");
					getConditionById(id).setHeightLab((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue())));
				}	
			}
			if(isOutput(id)){
				if(getOutput(id).getName()!=null){
					NodeList nodeLabelList = containerElement.getElementsByTagName("label");
					Node labelNode = nodeLabelList.item(0);
					nodeAttributesList = ((Element)labelNode).getElementsByTagName("attributes");
					attributesNode = nodeAttributesList.item(0);
					nodeBoundsList = ((Element)attributesNode).getElementsByTagName("bounds");
					boundsNode = nodeBoundsList.item(0);

					boundsNodeAttr = boundsNode.getAttributes();
					Node nodeValue = boundsNodeAttr.getNamedItem("x");
					getOutput(id).setCoordLabX((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue())));
					nodeValue = boundsNodeAttr.getNamedItem("y");
					getOutput(id).setCoordLabY((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue())));
					nodeValue = boundsNodeAttr.getNamedItem("w");
					getOutput(id).setWidthLab((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue())));
					nodeValue = boundsNodeAttr.getNamedItem("h");
					getOutput(id).setHeightLab((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue())));
				}
			}
		}
		NodeList nodeVertexIdList = elem.getElementsByTagName("vertex");
		for(int c = 0; c < nodeVertexIdList.getLength(); c++){
			Node containerNode = nodeVertexIdList.item(c);
			Element containerIdElement = (Element) containerNode;
			if(containerIdElement.hasAttributes()){
				NamedNodeMap conteinerIdElementList = containerIdElement.getAttributes();
				Node aAttr = conteinerIdElementList.getNamedItem( "id" );
				String id = aAttr.getNodeValue();

				//Vertex from the container
				NodeList nodeAttributesList = containerIdElement.getElementsByTagName("attributes");
				Node attributesNode = nodeAttributesList.item(0);
				NodeList nodeBoundsList = ((Element)attributesNode).getElementsByTagName("bounds");
				Node boundsNode = nodeBoundsList.item(0);

				NamedNodeMap boundsNodeAttr = boundsNode.getAttributes();
				if(isTask(id)){
					Task newTask = getTaskById(id);
					//newTask.setId(id);
					Node nodeValueX = boundsNodeAttr.getNamedItem( "x" );
					newTask.setCoordX((int)Float.parseFloat(parseFloat(nodeValueX.getNodeValue())));
					Node nodeValueY = boundsNodeAttr.getNamedItem( "y" );
					newTask.setCoordY((int)Float.parseFloat(parseFloat(nodeValueY.getNodeValue())));
					Node nodeValueW = boundsNodeAttr.getNamedItem( "w" );
					newTask.setWidth((int)Float.parseFloat(parseFloat(nodeValueW.getNodeValue())));
					Node nodeValueH = boundsNodeAttr.getNamedItem( "h" );
					newTask.setHeight((int)Float.parseFloat(parseFloat(nodeValueH.getNodeValue())));
					diagram.getTasks().add(newTask);
				}else{
					if(isCondition(id)){
						Node nodeValueX = boundsNodeAttr.getNamedItem( "x" );
						getConditionById(id).setCoordX((int)Float.parseFloat(parseFloat(nodeValueX.getNodeValue())));
						Node nodeValueY = boundsNodeAttr.getNamedItem( "y" );
						getConditionById(id).setCoordY((int)Float.parseFloat(parseFloat(nodeValueY.getNodeValue())));
						Node nodeValueW = boundsNodeAttr.getNamedItem( "w" );
						getConditionById(id).setWidth((int)Float.parseFloat(parseFloat(nodeValueW.getNodeValue())));
						Node nodeValueH = boundsNodeAttr.getNamedItem( "h" );
						getConditionById(id).setHeight((int)Float.parseFloat(parseFloat(nodeValueH.getNodeValue())));
					}			
				}
			}
		}
		for(int i=0;i<diagram.getInputs().size();i++){
			Input newInput = diagram.getInputs().get(i); 
			NodeList vertexList = elem.getElementsByTagName("vertex");
			for(int j = 0; j < vertexList.getLength(); j++){
				Node vertexNode = vertexList.item(j);
				Element vertexElement = (Element) vertexNode;
				if(vertexElement.hasAttributes()){
					NamedNodeMap vertexLista = vertexElement.getAttributes();
					Node idAttr = vertexLista.getNamedItem( "id" );
					String idAuxi = idAttr.getNodeValue();
					if((newInput.getId()).compareTo(idAuxi)==0){
						NodeList nodeAttributesList = ((Element)vertexNode).getElementsByTagName("attributes");
						Node attributesNode = nodeAttributesList.item(0);
						NodeList nodeBoundsList = ((Element)attributesNode).getElementsByTagName("bounds");
						Node boundsNode = nodeBoundsList.item(0);

						NamedNodeMap boundsNodeAttr = boundsNode.getAttributes();
						Node nodeValue = boundsNodeAttr.getNamedItem( "x" );
						newInput.setCoordX((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue())));

						nodeValue = boundsNodeAttr.getNamedItem( "y" );
						newInput.setCoordY((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue())));

						nodeValue = boundsNodeAttr.getNamedItem( "w" );
						newInput.setWidth((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue())));
						nodeValue = boundsNodeAttr.getNamedItem( "h" );
						newInput.setHeight((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue())));
					}
				}
			}
		}

		for(int i=0;i<diagram.getOutputs().size();i++){
			Output newOutput = diagram.getOutputs().get(i); 
			NodeList vertexList = elem.getElementsByTagName("vertex");
			for(int j = 0; j < vertexList.getLength(); j++){
				Node vertexNode = vertexList.item(j);
				Element vertexElement = (Element) vertexNode;
				if(vertexElement.hasAttributes()){
					NamedNodeMap vertexLista = vertexElement.getAttributes();
					Node idAttr = vertexLista.getNamedItem( "id" );
					String idAuxi = idAttr.getNodeValue();
					if((newOutput.getId()).compareTo(idAuxi)==0){
						NodeList nodeAttributesList = ((Element)vertexNode).getElementsByTagName("attributes");
						Node attributesNode = nodeAttributesList.item(0);
						NodeList nodeBoundsList = ((Element)attributesNode).getElementsByTagName("bounds");
						Node boundsNode = nodeBoundsList.item(0);

						NamedNodeMap boundsNodeAttr = boundsNode.getAttributes();
						Node nodeValue = boundsNodeAttr.getNamedItem( "x" );
						newOutput.setCoordX((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue())));
						nodeValue = boundsNodeAttr.getNamedItem( "y" );
						newOutput.setCoordY((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue())));
						nodeValue = boundsNodeAttr.getNamedItem( "w" );
						newOutput.setWidth((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue())));
						nodeValue = boundsNodeAttr.getNamedItem( "h" );
						newOutput.setHeight((int)Float.parseFloat(parseFloat(nodeValue.getNodeValue())));
					}
				}
			}
		}
		parseDecoratorTask(elem);
		parseFlow(elem);
	}

	private void parseDecoratorTask(Element elem){
		NodeList nodeContainerList = elem.getElementsByTagName("container");
		for(int c = 0; c < nodeContainerList.getLength(); c++){
			Node containerNode = nodeContainerList.item(c);
			Element containerElement = (Element) containerNode;

			NamedNodeMap elementIdList = containerElement.getAttributes();
			Node idAttr = elementIdList.getNamedItem( "id" );
			String id = idAttr.getNodeValue();

			NodeList decoratorList = containerElement.getElementsByTagName("decorator");			
			for(int d = 0;d<decoratorList.getLength();d++){
				Node decoratorNode = decoratorList.item(d);
				Element decoratorElement = (Element) decoratorNode;

				NamedNodeMap elementDecorList = decoratorElement.getAttributes();
				Node typeAttr = elementDecorList.getNamedItem( "type" );
				String type = typeAttr.getNodeValue();

				DecoratorTask decorate = new DecoratorTask();
				if(type.toLowerCase().indexOf("join") != -1){
					decorate.setDecorType("join");
					if(type.toLowerCase().indexOf("xor") != -1){
						decorate.setDecor("xor");
						getTaskById(id).setDecorJoin(decorate);
					}else
						if(type.toLowerCase().indexOf("and") != -1){
							decorate.setDecor("and");
							getTaskById(id).setDecorJoin(decorate);
						}else
							if(type.toLowerCase().indexOf("or") != -1){
								decorate.setDecor("or");
								getTaskById(id).setDecorJoin(decorate);
							}else{
								decorate.setDecor("none");
								getTaskById(id).setDecorJoin(decorate);
							}
					getTaskById(id).setDecorJoin(decorate);
				}else{
					decorate.setDecorType("split");
					if(type.toLowerCase().indexOf("xor") != -1){
						decorate.setDecor("xor");
						getTaskById(id).setDecorSplit(decorate);
					}else
						if(type.toLowerCase().indexOf("and") != -1){
							decorate.setDecor("and");
							getTaskById(id).setDecorSplit(decorate);
						}else
							if(type.toLowerCase().indexOf("or") != -1){
								decorate.setDecor("or");
								getTaskById(id).setDecorSplit(decorate);
							}else{
								decorate.setDecor("none");
								getTaskById(id).setDecorSplit(decorate);
							}
					getTaskById(id).setDecorSplit(decorate);
				}
				NodeList nodeAttributesList = decoratorElement.getElementsByTagName("attributes");
				Node attributesNode = nodeAttributesList.item(0);
				NodeList nodeBoundsList = ((Element)attributesNode).getElementsByTagName("bounds");
				Node boundsNode = nodeBoundsList.item(0);

				NamedNodeMap boundsNodeAttr = boundsNode.getAttributes();
				Node nodeValueX = boundsNodeAttr.getNamedItem( "x" );
				decorate.setCoordDecorX((int)Float.parseFloat(parseFloat(nodeValueX.getNodeValue())));
				Node nodeValueY = boundsNodeAttr.getNamedItem( "y" );
				decorate.setCoordDecorY((int)Float.parseFloat(parseFloat(nodeValueY.getNodeValue())));
				Node nodeValueW = boundsNodeAttr.getNamedItem( "w" );
				decorate.setWidthDecor((int)Float.parseFloat(parseFloat(nodeValueW.getNodeValue())));
				Node nodeValueH = boundsNodeAttr.getNamedItem( "h" );
				decorate.setHeightDecor((int)Float.parseFloat(parseFloat(nodeValueH.getNodeValue())));
			}
		}
		setUpdateTask();
	}

	private void parseInput(Element elem){
		NodeList nodeInputList = elem.getElementsByTagName("inputCondition");
		for(int c = 0; c < nodeInputList.getLength(); c++){
			Node containerNode = nodeInputList.item(c);
			Element inputElement = (Element) containerNode;
			Input newInput = new Input();

			NamedNodeMap elementIdList = inputElement.getAttributes();
			Node unAtributo = elementIdList.getNamedItem( "id" );
			String id = unAtributo.getNodeValue();

			newInput.setId(id);
			diagram.getInputs().add(newInput);
		}
	}

	private void parseCondition(Element elem){
		NodeList nodeConditionList = elem.getElementsByTagName("condition");			
		for (int s = 0; s < nodeConditionList.getLength(); s++) {
			Node conditionNodo = nodeConditionList.item(s);
			Element conditionElement = (Element) conditionNodo;
			Condition newCondition = new Condition();

			NamedNodeMap conditionElementList = conditionElement.getAttributes();
			Node conditionNode = conditionElementList.getNamedItem( "id" );
			String id = conditionNode.getNodeValue();
			newCondition.setId(id);

			NodeList nameElementoLista = conditionElement.getElementsByTagName("name");
			if(nameElementoLista.getLength()>0){
				Element nameElement = (Element) nameElementoLista.item(0);
				NodeList primerNombre = nameElement.getChildNodes();
				String name = ((Node) primerNombre.item(0)).getNodeValue().toString();
				newCondition.setName(name);
			}
			diagram.getConditions().add(newCondition);
		}
	}

	private void parseTask(Document doc,Element elem,LinkedList<String> noNetList,LinkedList<String> netList, LinkedList<Diagram> currentNetwork){
		NodeList nodeTaskList = elem.getElementsByTagName("task");			
		for (int s = 0; s < nodeTaskList.getLength(); s++) {
			Node taskNode = nodeTaskList.item(s);
			Element taskElement = (Element) taskNode;

			NamedNodeMap taskElementList = taskElement.getAttributes();
			Node aAttr = taskElementList.getNamedItem( "id" );
			String idAux = aAttr.getNodeValue();

			Task newTask = new Task();
			if(!isCondition(idAux) || !isTask(idAux)){
				newTask.setId(idAux);
				NodeList taskNamedList = taskElement.getElementsByTagName("name");
				if(taskNamedList.getLength()>0){
					Element taskNamed = (Element) taskNamedList.item(0);
					NodeList nameTask = taskNamed.getChildNodes();
					String name = ((Node) nameTask.item(0)).getNodeValue().toString();
					newTask.setName(name);
				}					
				diagram.getTasks().add(newTask);
			}

			NodeList taskRemoveTokenList = taskElement.getElementsByTagName("removesTokens");
			for(int i=0; i<taskRemoveTokenList.getLength();i++){
				Node taskRemoveToken = taskRemoveTokenList.item(i);
				Element elementRemoveToken = (Element) taskRemoveToken;

				NamedNodeMap elementRemoveTokenList = elementRemoveToken.getAttributes();
				Node idAttr = elementRemoveTokenList.getNamedItem( "id" );
				String id = idAttr.getNodeValue();
				newTask.setCanceller(true);
				newTask.addRemoveToken(id);
			}

			NodeList taskDecList = taskElement.getElementsByTagName("decomposesTo");
			if(taskDecList.getLength()>0){
				NamedNodeMap idDecList = taskElement.getAttributes();
				aAttr = idDecList.getNamedItem( "id" );
				String id = aAttr.getNodeValue();
				if(!noNetList.contains(id)){
					parseDecomposite(doc,elem,noNetList,netList,currentNetwork);
				}
			}
		}
	}

	private void parseOutput(Element elem){
		NodeList nodeOutputList = elem.getElementsByTagName("outputCondition");
		for(int c = 0; c < nodeOutputList.getLength(); c++){
			Node containerNode = nodeOutputList.item(c);
			Element outputElement = (Element) containerNode;
			Output newOutput = new Output();

			NamedNodeMap primerIdElementoLista = outputElement.getAttributes();
			Node unAtributo = primerIdElementoLista.getNamedItem( "id" );
			String id = unAtributo.getNodeValue();
			newOutput.setId(id);

			NodeList taskNamedList = elem.getElementsByTagName("name");
			if(taskNamedList.getLength()>0){
				Element taskNamed = (Element) taskNamedList.item(0);
				NodeList nameTask = taskNamed.getChildNodes();
				String name = ((Node) nameTask.item(0)).getNodeValue().toString();
				newOutput.setName(name);
			}

			diagram.getOutputs().add(newOutput);
		}
	}

	private void parseFlow(Element elem){
		NodeList nodeFlowList = elem.getElementsByTagName("flow");
		for(int c = 0; c < nodeFlowList.getLength(); c++){
			Node flowNode = nodeFlowList.item(c);
			Element flowElement = (Element) flowNode;
			Flow newFlow = new Flow();

			NamedNodeMap primerIdElementoLista = flowElement.getAttributes();
			Node unAtributo = primerIdElementoLista.getNamedItem( "source" );
			String source = unAtributo.getNodeValue();
			if(isCondition(source)){
				newFlow.setSource(getConditionById(source));
				getConditionById(source).addFlowsOut(newFlow);
			}
			if(isTask(source)){
				newFlow.setSource(getTaskById(source));
				getTaskById(source).addFlowsOut(newFlow);
			}
			if(isInput(source)){
				newFlow.setSource(getInput(source));
				getInput(source).addFlowsOut(newFlow);
			}
			unAtributo = primerIdElementoLista.getNamedItem( "target" );
			String target = unAtributo.getNodeValue();
			if(isCondition(target)){
				newFlow.setTarget(getConditionById(target));
				(getConditionById(target)).addFlowsIn(newFlow);
			}
			if(isTask(target)){
				newFlow.setTarget(getTaskById(target));
				(getTaskById(target)).addFlowsIn(newFlow);
			}
			if(isOutput(target)){
				newFlow.setTarget(getOutput(target));
				getOutput(target).addFlowsIn(newFlow);
			}
			NodeList nodeAttributesList = ((Element)flowNode).getElementsByTagName("attributes");
			Node attributesNode = nodeAttributesList.item(0);
			NodeList nodePointsList = ((Element)attributesNode).getElementsByTagName("points");
			Node pointsNode = nodePointsList.item(0);
			NodeList nodeValueList = null;
			if(nodePointsList.getLength()>0)
				nodeValueList  = ((Element)pointsNode).getElementsByTagName("value");

			Point newPoint = new Point();
			Point newPoint1 = new Point();
			readPointsFlow(newFlow, source, target, nodeValueList, newPoint, newPoint1);
			diagram.getFlows().add(newFlow);
		}
	}

	private void readPointsFlow(Flow newFlow, String source, String target,
			NodeList nodeValueList, Point newPoint, Point newPoint1) {
		//sources
		Condition nCondIn = getConditionById(source);
		Task nTaskIn = getTaskById(source);
		Input nInputIn = getInput(source);

		//targets
		Condition nCondOut = getConditionById(target);
		Task nTaskOut = getTaskById(target);
		Output nOutputOut = getOutput(target);

		if(isCondition(source)){
			if(nTaskOut != null){
				simpleElementSourcePoint(newPoint, nCondIn, nTaskOut);
			}
		}
		if(isTask(source)){			
			if(nTaskIn.getPortSplit()!=null){
				newPoint.setLocation(nTaskIn.getPortSplit().x,nTaskIn.getPortSplit().y);
			}else{
				if(nTaskOut!=null){
					simpleElementSourcePoint(newPoint, nTaskIn, nTaskOut);
					//nTaskIn.setPortSplit(newPoint);
				}else if(nCondOut != null){	
					simpleElementSourcePoint(newPoint, nTaskIn, nCondOut);
					//nTaskIn.setPortSplit(newPoint);
				}else if(nOutputOut != null){
					simpleElementSourcePoint(newPoint, nTaskIn, nOutputOut);
					//nTaskIn.setPortSplit(newPoint);
				}
			}
		}
		if(isInput(source)){
			if(nTaskOut != null){	
				simpleElementSourcePoint(newPoint, nInputIn, nTaskOut);
			}
		}
		newFlow.setCoordenates(newPoint);

		//target flows initialization
		if(isCondition(target)){
			if(nTaskIn != null){
				simpleElementTargetPoint(newPoint1, nTaskIn, nCondOut);
			}
		}
		if(isTask(target)){
			if(nTaskOut.getPortJoin()!=null){
				newPoint1.setLocation(nTaskOut.getPortJoin().x,nTaskOut.getPortJoin().y);
			}else{
				if(nTaskIn!=null){
					simpleElementTargetPoint(newPoint1, nTaskIn, nTaskOut);
					//nTaskOut.setPortJoin(newPoint1);
				}else if(nCondIn != null){	
					simpleElementTargetPoint(newPoint1, nCondIn, nTaskOut);
					//nTaskOut.setPortJoin(newPoint1);
				}else if(nInputIn != null){	
					simpleElementTargetPoint(newPoint1, nInputIn, nTaskOut);
					//nTaskOut.setPortJoin(newPoint1);
				}
			}
		}
		if(isOutput(target)){
			if(nTaskIn != null){
				simpleElementTargetPoint(newPoint1, nTaskIn, nOutputOut);
			}
		}
		newFlow.setCoordenates(newPoint1);

	}

	private void simpleElementTargetPoint(Point newPoint1, State source,
			State target) {
		if(target.getCoordY() > source.getCoordY()+source.getHeight() + RANGE_FLOW ){
			if(target.getCoordX()+target.getWidth() > source.getCoordX()- RANGE_FLOW){
				if (target.getCoordX() + target.getWidth() < source.getCoordX() + source.getWidth() + RANGE_FLOW){
					newPoint1.setLocation(target.getCoordX()+(target.getWidth()/2),target.getCoordY()); //NORTH POINT OF THE CONDITION
				}else{
					newPoint1.setLocation(target.getCoordX(),target.getCoordY()+(target.getHeight()/2));//WEST POINT OF THE CONDITION
				}
			}else{
				newPoint1.setLocation(target.getCoordX()+(target.getWidth()),target.getCoordY()+(target.getHeight()/2)); //EAST POINT OF THE CONDITION
			}
		}else{ 
			if(target.getCoordY()+ target.getHeight() < source.getCoordY() - RANGE_FLOW ){
				if(target.getCoordX()+target.getWidth() > source.getCoordX()- RANGE_FLOW){
					if (target.getCoordX()+target.getWidth()< source.getCoordX() + source.getWidth() + RANGE_FLOW){
						newPoint1.setLocation(target.getCoordX()+(target.getWidth()/2),target.getCoordY()+(target.getHeight())); //SOUTH POINT OF THE CONDITION
					}else{
						newPoint1.setLocation(target.getCoordX(),target.getCoordY()+(target.getHeight()/2));//WEST POINT OF THE CONDITION
					}
				}else{
					newPoint1.setLocation(target.getCoordX()+(target.getWidth()),target.getCoordY()+(target.getHeight()/2)); //EAST POINT OF THE CONDITION
				}
			}else{
				if (target.getCoordX()+target.getWidth()< source.getCoordX() + source.getWidth() + RANGE_FLOW){
					newPoint1.setLocation(target.getCoordX()+(target.getWidth()),target.getCoordY()+(target.getHeight()/2)); //EAST POINT OF THE CONDITION
				}else{
					newPoint1.setLocation(target.getCoordX(),target.getCoordY()+(target.getHeight()/2));//WEST POINT OF THE CONDITION
				}
			}
		}
	}

	private void simpleElementSourcePoint(Point newPoint, State source, State target) {
		if(target.getCoordY() > source.getCoordY()+source.getHeight() + RANGE_FLOW ){
			if(target.getCoordX()+target.getWidth() > source.getCoordX()- RANGE_FLOW){
				if (target.getCoordX() + target.getWidth() < source.getCoordX() + source.getWidth() + RANGE_FLOW){
					newPoint.setLocation(source.getCoordX()+(source.getWidth()/2),source.getCoordY()+(source.getHeight())); //SOUTH POINT OF THE CONDITION
				}else{
					newPoint.setLocation(source.getCoordX()+(source.getWidth()),source.getCoordY()+(source.getHeight()/2)); //EAST POINT OF THE CONDITION
				}
			}else{
				newPoint.setLocation(source.getCoordX(),source.getCoordY()+(source.getHeight()/2));//WEST POINT OF THE CONDITION
			}
		}else{ 
			if(target.getCoordY()+ target.getHeight() < source.getCoordY() - RANGE_FLOW ){
				if(target.getCoordX()+target.getWidth() > source.getCoordX()- RANGE_FLOW){
					if (target.getCoordX()+target.getWidth()< source.getCoordX() + source.getWidth() + RANGE_FLOW){
						newPoint.setLocation(source.getCoordX()+(source.getWidth()/2),source.getCoordY()); //NORTH POINT OF THE CONDITION
					}else{
						newPoint.setLocation(source.getCoordX()+(source.getWidth()),source.getCoordY()+(source.getHeight()/2)); //EAST POINT OF THE CONDITION
					}
				}else{
					newPoint.setLocation(source.getCoordX(),source.getCoordY()+(source.getHeight()/2));//WEST POINT OF THE CONDITION
				}
			}else{
				if (target.getCoordX()+target.getWidth()< source.getCoordX() + source.getWidth() + RANGE_FLOW){
					newPoint.setLocation(source.getCoordX(),source.getCoordY()+(source.getHeight()/2));//WEST POINT OF THE CONDITION
				}else{
					newPoint.setLocation(source.getCoordX()+(source.getWidth()),source.getCoordY()+(source.getHeight()/2)); //EAST POINT OF THE CONDITION
				}
			}
		}
	}


	private Task getTaskById(String idTask){
		for(int i = 0;i<diagram.getTasks().size();i++){
			if(diagram.getTasks().get(i).getId().compareTo(idTask)==0){
				return diagram.getTasks().get(i);
			}
		}
		return null;
	}

	private Condition getConditionById(String idCondition){
		for(int i=0;i<diagram.getConditions().size();i++){
			if((diagram.getConditions().get(i).getId()).compareTo(idCondition)==0)
				return diagram.getConditions().get(i);
		}
		return null;
	}

	private void setSize(Element elem){		
		NodeList nodeSizeList = elem.getElementsByTagName("bounds");
		if(nodeSizeList.getLength()>0){
			Node sizeNode = nodeSizeList.item(0);
			Element sizeElement = (Element) sizeNode;

			NamedNodeMap sizeElementList = sizeElement.getAttributes();
			Node wSize = sizeElementList.getNamedItem( "w" );
			int w = Integer.parseInt(wSize.getNodeValue());

			sizeElementList = sizeElement.getAttributes();
			Node hSize = sizeElementList.getNamedItem( "h" );
			int h= Integer.parseInt(hSize.getNodeValue());

			this.diagram.setSize(new Dimension(w, h));
		}
	}

	private boolean isTask(String idTask){
		for(int i=0;i<diagram.getTasks().size();i++){
			if((diagram.getTasks().get(i).getId()).compareTo(idTask)==0)
				return true;
		}
		return false;
	}

	private boolean isCondition(String idCondition){
		for(int i=0;i<diagram.getConditions().size();i++){
			if((diagram.getConditions().get(i).getId()).compareTo(idCondition)==0)
				return true;
		}
		return false;
	}

	private boolean isInput(String idInput){
		for(int i=0;i<diagram.getInputs().size();i++){
			if((diagram.getInputs().get(i).getId()).compareTo(idInput)==0)
				return true;
		}
		return false;
	}

	private Input getInput(String idInput){
		for(int i=0;i<diagram.getInputs().size();i++){
			if((diagram.getInputs().get(i).getId()).compareTo(idInput)==0)
				return diagram.getInputs().get(i);
		}
		return null;
	}

	private boolean isOutput(String idOutput){
		for(int i=0;i<diagram.getOutputs().size();i++){
			if((diagram.getOutputs().get(i).getId()).compareTo(idOutput)==0)
				return true;
		}
		return false;
	}

	private Output getOutput(String idOutput){
		for(int i=0;i<diagram.getOutputs().size();i++){
			if((diagram.getOutputs().get(i).getId()).compareTo(idOutput)==0)
				return diagram.getOutputs().get(i);
		}
		return null;
	}

	public Diagram getDiagram(){
		return this.diagram;
	}

	public LinkedList<Diagram> getListDiagrams(){
		return this.diagramsNetwork;
	}

	private String parseFloat(String str){
		return str.replace(',','.');
	}

	private void setUpdateTask(){
		for(int t=0;t<diagram.getTasks().size();t++){	
			Task currenTask = diagram.getTasks().get(t);
			if(currenTask.getDecorJoin() != null){
				if(currenTask.getDecorJoin().getCoordDecorX() < currenTask.getCoordX()){
					currenTask.setPortJoin(new Point(currenTask.getDecorJoin().getCoordDecorX(),currenTask.getDecorJoin().getCoordDecorY()+(currenTask.getDecorJoin().getHeightDecor()/2)));
				}
				if(currenTask.getDecorJoin().getCoordDecorX() > currenTask.getCoordX()){

					currenTask.setPortJoin(new Point(currenTask.getDecorJoin().getCoordDecorX()+currenTask.getDecorJoin().getWidthDecor(),currenTask.getDecorJoin().getCoordDecorY()+(currenTask.getDecorJoin().getHeightDecor()/2)));
				}
				if(currenTask.getDecorJoin().getCoordDecorY() < currenTask.getCoordY()){
					currenTask.setPortJoin(new Point(currenTask.getDecorJoin().getCoordDecorX()+(currenTask.getDecorJoin().getWidthDecor()/2),currenTask.getDecorJoin().getCoordDecorY()));
				}
				if(currenTask.getDecorJoin().getCoordDecorY() > currenTask.getCoordY()){
					currenTask.setPortJoin(new Point(currenTask.getDecorJoin().getCoordDecorX()+(currenTask.getDecorJoin().getWidthDecor()/2),currenTask.getDecorJoin().getCoordDecorY()+currenTask.getDecorJoin().getHeightDecor()));
				}
			}
			if(currenTask.getDecorSplit()!=null){
				if(currenTask.getDecorSplit().getCoordDecorX() > currenTask.getCoordX()){
					currenTask.setPortSplit(new Point(currenTask.getDecorSplit().getCoordDecorX()+currenTask.getDecorSplit().getWidthDecor(),currenTask.getDecorSplit().getCoordDecorY()+(currenTask.getDecorSplit().getHeightDecor()/2)));
				}
				if(currenTask.getDecorSplit().getCoordDecorX() < currenTask.getCoordX()){
					currenTask.setPortSplit(new Point(currenTask.getDecorSplit().getCoordDecorX(),currenTask.getDecorSplit().getCoordDecorY()+(currenTask.getDecorSplit().getHeightDecor()/2)));
				}
				if(currenTask.getDecorSplit().getCoordDecorY() > currenTask.getCoordY()){
					currenTask.setPortSplit(new Point(currenTask.getDecorSplit().getCoordDecorX()+(currenTask.getDecorSplit().getWidthDecor()/2),currenTask.getDecorSplit().getCoordDecorY()+currenTask.getDecorSplit().getHeightDecor()));
				}
				if(currenTask.getDecorSplit().getCoordDecorY() < currenTask.getCoordY()){
					currenTask.setPortSplit(new Point(currenTask.getDecorSplit().getCoordDecorX()+(currenTask.getDecorSplit().getWidthDecor()/2),currenTask.getDecorSplit().getCoordDecorY()));
				}
			}
		}
	}

	private double pend(double x1,double y1,double x2,double y2){
		if((x2 - x1)==0)
			return 0;
		return (y2 - y1)/(x2 - x1);
	}

	private void setCompositeTask(LinkedList<String> netsList){
		for(int i = 0;i<netsList.size();i++ ){
			String idNet = netsList.get(i);
			for(Task task : diagram.getTasks()){
				if(task.getId().contains(idNet)){
					task.setComposite(true);
					break;
				}
			}
		}
	}
}

